import { InsertResult, Repository } from "typeorm";
import { UserDao } from "../../account_server/dao/UserDao";
import { UserEntity } from "../../account_server/entity/UserEntity";
import { LogServerHelper } from "../../log_server/LogServerHelper";
import { DbConfig } from "../../src/config/DbConfig";
import { ErrorCode } from "../../src/config/ErrorCode";
import { GameConfig } from "../../src/config/GameConfig";
import { DaoBase } from "../../src/engine/dao/DaoBase";
import { Base64Helper } from "../../src/engine/utils/Base64Helper";
import DateUtil from "../../src/engine/utils/DateUtil";
import { DBSourceManager } from "../../src/engine/utils/DBSourceManager";
import { Logger } from "../../src/engine/utils/Logger";
import { MysqlClient } from "../../src/engine/utils/MySqlClient";
import { MysqlManager } from "../../src/engine/utils/MysqlManager";
import RandomUtil from "../../src/engine/utils/RandomUtil";
import { JhaoProto } from "../../src/lib/net/protobuf/jhaoproto";
import { ResponseModel } from "../../src/model/ResponseModel";
import { ClubConfig } from "../config/ClubConfig";
import { ClubEntity } from "../entity/ClubEntity";
import { ClubUserEntity } from "../entity/ClubUserEntity";
import { ClubModel } from "../model/ClubModel";
import { ClubUserDao } from "./ClubUserDao";
import { RoomDao } from "./RoomDao";

export class ClubDao extends DaoBase {

    public static async getRepository() {
        let repository: Repository<ClubEntity> = await this.getRepositoryBase(ClubEntity, this.getGameDbName())
        return repository;
    }


    public static async randomClubId(randomCount: number = 0) {
        let clubid: number = RandomUtil.nextInt(100000, 999999)
        let isExist: ClubEntity = await this.is_club_exist(clubid)
        if (!isExist) {
            return clubid
        } else {
            // Logger.log("randomClubId==", randomCount)
            randomCount++;
            if (randomCount > 5) {
                Logger.error("randomClubId 俱乐部id重复", clubid)
                return 0
            } else {
                return this.randomClubId(randomCount)
            }
        }
    }

    public static async is_club_exist(clubid: number): Promise<ClubEntity> {
        let repository: Repository<ClubEntity> = await this.getRepository()
        let result: ClubEntity = await repository.findOneBy({
            clubid: clubid
        })
        return result
    }

    public static async create_club(clubEntity: ClubEntity): Promise<boolean> {
        let repository: Repository<ClubEntity> = await this.getRepository()
        let result: InsertResult = await DBSourceManager.instance.insert(repository, clubEntity)
        if (result && result.raw["affectedRows"] > 0) {
            let isSuc: boolean = await ClubUserDao.add_club_user(clubEntity.clubid, clubEntity.creator, ClubConfig.Club_Actor_Type.owner, ClubConfig.Club_merber_state_type.nomal)
            if (isSuc) {
                return true
            } else {
                return false
            }
        }
        return false
    }

    public static async get_club_simple(userid: number, clubid: number):Promise<JhaoProto.IClubInfo> {
        let sql = `select * from t_clubusers,t_clublist,t_users where t_clubusers.userid = ? and  t_clublist.clubid=? and t_clubusers.clubid = t_clublist.clubid  and  t_clubusers.userid = t_users.userid and (t_clubusers.state = ? or t_clubusers.state = ?)`
        let repository: Repository<ClubEntity> = await this.getRepository()
        let sqlParams: Array<any> = [userid,clubid, ClubConfig.Club_merber_state_type.nomal, ClubConfig.Club_merber_state_type.freeze];
        let results = await repository.query(sql, sqlParams)
        Logger.log("get_club_simple===", sql, sqlParams)
        Logger.log("get_club_simple=2==",results)
        if (!results || !results.length) {
            return null
        }
        let club:JhaoProto.IClubInfo = ClubModel.data2IClubInfo(results[0])
        return club
    }


    public static async get_club_list(userid: number) {
        let sql = `select * from t_clubusers,t_clublist,t_users where t_clubusers.userid = ? and t_clubusers.clubid = t_clublist.clubid  and  t_clubusers.userid = t_users.userid and t_clubusers.user_state=?`
        let repository: Repository<ClubEntity> = await this.getRepository()
        let sqlParams: Array<any> = [userid, ClubConfig.Club_merber_state_type.nomal];

        let results = await repository.query(sql, sqlParams)
        Logger.log("get_club_list=", results)
        if (!results || !results.length) {
            return []
        }
        let clubs = results
        for (let i = 0; i < clubs.length; i++) {
            let clubid = clubs[i]["clubid"]
            // 玩家数
            clubs[i]["usercount"] = await ClubUserDao.getUserCountByClub(clubid)
        }
        Logger.log("get_club_list=", clubs)

        let resultClubs: Array<JhaoProto.IClubInfo> = ClubModel.data2IClubInfoList(clubs);
        return resultClubs
    }

    public static async join_club(userid: number, clubid: number) {
        let respModel: ResponseModel = new ResponseModel()
        let clubEntity: ClubEntity = await this.is_club_exist(clubid)
        if (!clubEntity) {
            respModel.code = ErrorCode.Code.Fail
            respModel.msg = "俱乐部不存在!"
        } else {
            let clubUserEntity:ClubUserEntity = await ClubUserDao.get_club_user(clubid, userid)
            let canApply: boolean = true
            let hadApply: boolean = false
            if (clubUserEntity) {
                let user_state: number = clubUserEntity.user_state
                if (user_state == ClubConfig.Club_merber_state_type.apply) {// 已申请，等待
                    respModel.code = ErrorCode.Code.Fail;
                    respModel.msg = "您已经提交过申请，请不要重复提交，等待管理员审核"
                    canApply = false
                } else if (user_state == ClubConfig.Club_merber_state_type.nomal) {// 已经是
                    respModel.code = ErrorCode.Code.Fail;
                    respModel.msg = "您已经是此亲友圈成员，无需再次申请"
                    canApply = false
                } else if (user_state == ClubConfig.Club_merber_state_type.refuse) {// 被拒绝
                    hadApply = true
                    clubUserEntity.user_state = ClubConfig.Club_merber_state_type.apply
                } else if (user_state == ClubConfig.Club_merber_state_type.blacklist) {// 黑名单
                    respModel.code = ErrorCode.Code.Fail;
                    respModel.msg = "您已经被此亲友圈拉入黑名单，无法申请"
                    canApply = false
                } else {
                    Logger.warn("未识别加入亲友圈状态:", user_state);
                    respModel.code = ErrorCode.Code.Fail;
                    respModel.msg = "您已经被此亲友圈拉入黑名单，无法申请"
                    canApply = false
                }
            }else{
                clubUserEntity = new ClubUserEntity()
                clubUserEntity.id = null
                clubUserEntity.clubid = clubid
                clubUserEntity.userid = userid
                clubUserEntity.user_state =  ClubConfig.Club_merber_state_type.apply
                clubUserEntity.actor =  ClubConfig.Club_Actor_Type.general
                clubUserEntity.join_time = DateUtil.formatDateStr(DateUtil.now())
            }
            if (canApply) {
                clubUserEntity = await ClubUserDao.update_user(clubUserEntity)
            }
        }
        return respModel;
    }


    public static async req_club_apply_list(clubid: number) {
        let sql = `select userid,nick_name,headimg, clubid,user_state,invite,lv from v_club_users where clubid = ? and user_state=0`
        let sqlParams: Array<any> = [clubid];
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let rows = await client.queryPromise(sql, sqlParams);
        let respModel: ResponseModel = new ResponseModel()
        if (rows) { //已经存在俱乐部数据
            respModel.code = ErrorCode.Code.Suc;
            respModel.data = rows;
        } else {
            respModel.code = ErrorCode.Code.Db_Error
            respModel.msg = "查询俱乐部申请列表失败"
        }
        return respModel
    }

    

    public static async agreeApply(handle_userid: number, apply_userid: number, clubid: number) {
        let sql: string = "update t_clubusers set `state`=1, `approver`=?  where `userid`=? and clubid=?";
        let sqlParams: Array<any> = [handle_userid, apply_userid, clubid];
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let rows = await client.queryPromise(sql, sqlParams);
        if (rows && rows["affectedRows"] > 0) {
            LogServerHelper.log_club_in_out_history(clubid, apply_userid, ClubConfig.in_out_type.be_in, handle_userid)
            return true
        }
        return false;
    }

    public static async disagreeApply(handle_userid: number, apply_userid: number, clubid: number) {
        let sql: string = "update t_clubusers set `state`=3, `approver`=?   where `userid`=? and clubid=?";
        let sqlParams: Array<any> = [handle_userid, apply_userid, clubid];
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let rows = await client.queryPromise(sql, sqlParams);
        if (rows && rows["affectedRows"] > 0) {
            return true
        }
        return false;
    }

    public static async get_v_club_user_view(clubid: number, userid: number) {
        let sql = `select * from v_club_users where clubid = ? and userid=?`
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sqlParams: Array<any> = [clubid, userid];
        let rows = await client.queryPromise(sql, sqlParams);
        if (rows && rows.length) { //已经存在俱乐部数据
            return rows[0]
        }
    }

    public static async get_v_club_user_list_by_page(clubid: number, page_size: number, cur_page: number) {
        let startIndex: number = (cur_page - 1) * page_size;
        let sql: string = "select * from v_club_users where clubid=? and (user_state=1 or user_state=2)  order by actor desc limit ?,?"
        let sqlParams: Array<any> = [clubid, startIndex, page_size];
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let rows = await client.queryPromise(sql, sqlParams);
        Logger.log("get_v_club_user_list_by_page==", sql, sqlParams, rows)
        if (rows && rows.length > 0) {
            return rows
        }
        return []
    }

    public static async getClubMerberTotalNum(clubid: number) {
        let sql: string = "select count(*) from t_clubusers where clubid=?"
        let sqlParams: Array<any> = [clubid];
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let rows = await client.queryPromise(sql, sqlParams);
        Logger.log("getClubMerberTotalNum==", clubid, rows)
        if (rows) {
            return rows[0]["count(*)"]
        }
        return 0
    }

    public static async delete_club_user(clubid: number, userid: number) {
        let sql: string = "delete from t_clubusers  where `userid`=? and clubid=?";
        let sqlParams: Array<any> = [userid, clubid];
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let rows = await client.queryPromise(sql, sqlParams);
        if (rows && rows["affectedRows"] > 0) {
            LogServerHelper.log_club_in_out_history(clubid, userid, ClubConfig.in_out_type.my_out, 0)
            return true
        }
        return false;
    }

    public static async delete_clut_users(clubid: number, useridList: Array<number>) {
        if (useridList.length > 0) {
            let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
            let sql = "delete from t_clubusers  where clubid=? and actor != " + ClubConfig.Club_Actor_Type.owner + "  and ( `userid`=" + useridList[0];
            for (let i = 1; i < useridList.length; i++) {
                sql += " or `userid`=" + useridList[i];
            }
            sql += " )"
            let sqlParams: Array<any> = [clubid];
            let results = await client.queryPromise(sql, sqlParams);
            Logger.log("delete_clut_users======", sql, results)
            if (results && results["affectedRows"] > 0) {
                return true
            }
        }
        return false
    }

    public static async add_club_table_group(clubid: number): Promise<boolean> {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = "insert into t_club_table_group (clubid) values(?);"
        let sqlParams: Array<any> = [clubid];
        let results = await client.queryPromise(sql, sqlParams);
        if (results && results["affectedRows"] > 0) {
            return true
        }
        else {
            return false
        }
    }

    public static async delete_club_table_group(id: number): Promise<boolean> {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = "delete from t_club_table_group where id=?"
        let sqlParams: Array<any> = [id];
        let results = await client.queryPromise(sql, sqlParams);
        if (results && results["affectedRows"] > 0) {
            return true
        }
        else {
            return false
        }
    }

    public static async get_club_table_group_no_userinfo(clubid: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = "select * from t_club_table_group where clubid=?"
        let sqlParams: Array<any> = [clubid];
        let rows = await client.queryPromise(sql, sqlParams);
        let resultList: Array<object> = []
        if (rows && rows.length > 0) {
            for (let i = 0; i < rows.length; i++) {
                let resultObj: object = {
                    "id": rows[i]["id"],
                    "clubid": rows[i]["clubid"],
                }
                let users: string = rows[i]["users"]
                if (users) {
                    let userArr: Array<string> = users.split(",");
                    let userids: Array<number> = []
                    for (let j = 0; j < userArr.length; j++) {
                        let userid: number = parseInt(userArr[j])
                        userids.push(userid)
                    }
                    resultObj["userids"] = userids;
                }
                resultList[i] = resultObj;
            }
        }
        return resultList
    }

    public static async get_club_table_group(clubid: number): Promise<any> {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = "select * from t_club_table_group where clubid=?"
        let sqlParams: Array<any> = [clubid];
        let rows = await client.queryPromise(sql, sqlParams);
        if (rows && rows.length > 0) {
            let alluseridList: Array<number> = []
            let resultList: Array<object> = []
            for (let i = 0; i < rows.length; i++) {
                let resultObj: object = {
                    "id": rows[i]["id"],
                    "clubid": rows[i]["clubid"],
                }
                let users: string = rows[i]["users"]
                if (users) {
                    let userArr: Array<string> = users.split(",");
                    let userids: Array<number> = []
                    for (let j = 0; j < userArr.length; j++) {
                        let userid: number = parseInt(userArr[j])
                        userids.push(userid)
                        if (!alluseridList.includes(userid)) {
                            alluseridList.push(userid)
                        }
                    }
                    resultObj["userids"] = userids;
                }
                resultList[i] = resultObj;
            }
            let userInfoList: Array<UserEntity> = await UserDao.get_userlistinfo(alluseridList)
            for (let i = 0; i < resultList.length; i++) {
                let resultObj: object = resultList[i]
                let resultUsers: Array<object> = []
                let userids: Array<number> = resultObj["userids"];
                if (userids && userids.length > 0) {
                    for (let j = 0; j < userInfoList.length; j++) {
                        let userid: number = userInfoList[j].userid
                        if (userids.includes(userid)) {
                            resultUsers.push(userInfoList[j])
                        }
                    }
                }
                resultObj["resultUsers"] = resultUsers;
            }
            return resultList
        }
        else {
            return null
        }
    }

    public static async add_user_to_club_group(id: number, userid: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = "select * from t_club_table_group where id=?"
        let sqlParams: Array<any> = [id];
        let rows = await client.queryPromise(sql, sqlParams);
        let respModel: ResponseModel = new ResponseModel();
        if (rows && rows.length) {
            let users: string = rows[0]["users"]
            if (users) {
                let userArr: Array<string> = users.split(",");
                if (userArr.includes(userid + "")) {
                    respModel.code = ErrorCode.Code.Fail
                    respModel.msg = "该用户已经在分组里面了"
                } else {
                    userArr.push(userid + "")
                    users = userArr.toString()
                    respModel.code = ErrorCode.Code.Suc
                }
            } else {
                users = userid + ""
                respModel.code = ErrorCode.Code.Suc
            }
            if (respModel.code == ErrorCode.Code.Suc) {
                sql = "update t_club_table_group set `users`=? where `id`=?";
                sqlParams = [users, id]
                rows = await client.queryPromise(sql, sqlParams);
                if (rows && rows["affectedRows"] > 0) {

                } else {
                    respModel.code = ErrorCode.Code.Db_Error
                    respModel.msg = "数据库更新分组失败"
                }
            }
        }
        else {
            respModel.code = ErrorCode.Code.Db_Error
            respModel.msg = "数据库查询不到该分组id"
        }
        return respModel;
    }

    public static async del_user_to_club_group(id: number, userid: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = "select * from t_club_table_group where id=?"
        let sqlParams: Array<any> = [id];
        let rows = await client.queryPromise(sql, sqlParams);
        let respModel: ResponseModel = new ResponseModel();
        if (rows && rows.length) {
            let users: string = rows[0]["users"]
            if (users) {
                let userArr: Array<string> = users.split(",");
                let index: number = userArr.indexOf(userid + "")
                userArr.splice(index, 1);
                users = userArr.toString()
                sql = "update t_club_table_group set `users`=? where `id`=?";
                sqlParams = [users, id]
                rows = await client.queryPromise(sql, sqlParams);
                if (rows && rows["affectedRows"] > 0) {

                } else {
                    respModel.code = ErrorCode.Code.Db_Error
                    respModel.msg = "数据库更新分组失败"
                }
            } else {
                respModel.code = ErrorCode.Code.Db_Error
                respModel.msg = "数据库查询不到该分组用户"
            }
        }
        else {
            respModel.code = ErrorCode.Code.Db_Error
            respModel.msg = "数据库查询不到该分组id"
        }
        return respModel;
    }


    public static async update_club_setting(clubid: number, seemember: number, seerank: number, limit_join: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = "update t_clublist set `seemember`=?,`seerank`=?,`limit_join`=?  where clubid=?"
        let sqlParams: Array<any> = [seemember, seerank, limit_join, clubid];
        let rows = await client.queryPromise(sql, sqlParams);
        if (rows && rows["affectedRows"] > 0) {
            return true;
        }
        return false
    }

    public static async update_club_state(clubid: number, state: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = "update t_clublist set `state`=?  where clubid=?"
        let sqlParams: Array<any> = [state, clubid];
        let rows = await client.queryPromise(sql, sqlParams);
        Logger.log("update_club_state===", sql, sqlParams, rows)
        if (rows && rows["affectedRows"] > 0) {
            return true;
        }
        return false
    }

    public static async delete_club(clubid: number) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = "delete from  t_clublist where clubid=?"
        let sqlParams: Array<any> = [clubid];
        let rows = await client.queryPromise(sql, sqlParams);
        if (rows && rows["affectedRows"] > 0) {
            sql = "delete from t_clubusers where clubid=?"
            rows = await client.queryPromise(sql, sqlParams);
            sql = "delete from t_club_table_group where clubid=?"
            rows = await client.queryPromise(sql, sqlParams);
            return true;
        }
        return false
    }

    public static async club_fix_notice(clubid: number, message: string) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = "update t_clublist set `message`=?  where clubid=?"
        let sqlParams: Array<any> = [message, clubid];
        let rows = await client.queryPromise(sql, sqlParams);
        if (rows && rows["affectedRows"] > 0) {
            return true;
        }
    }

    public static async set_club_administrator(clubid: number, userid: number, actor: number, quanxian: string) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = "update t_clubusers set `actor`=?,`quanxian`=? where `userid`=? and `clubid`=? "
        let sqlParams: Array<any> = [actor, quanxian, userid, clubid];
        let rows = await client.queryPromise(sql, sqlParams);
        if (rows && rows["affectedRows"] > 0) {
            return true;
        }
        return false
    }

    public static async set_club_member_quanxian(clubid: number, userid: number, quanxian: string) {
        let client: MysqlClient = await MysqlManager.instance.getDb(this.getGameDbName());
        let sql: string = "update t_clubusers set `quanxian`=? where `userid`=? and `clubid`=? "
        let sqlParams: Array<any> = [quanxian, userid, clubid];
        let rows = await client.queryPromise(sql, sqlParams);
        if (rows && rows["affectedRows"] > 0) {
            return true;
        }
        return false
    }


}